﻿using SoftwareConsulting.BI11.NumericalMethods.Interfaces;
using SoftwareConsulting.BI11.NumericalMethods.Iterations;

namespace SoftwareConsulting.BI11.NumericalMethods.Optimization
{
    /// <summary>
    /// Класс абстрактного оптимизатора многопеременных функций
    /// </summary>
    public abstract class MultiVariableOptimizer : IterativeProcess
    {	    
        private IManyVariableFunction _function;//оптимизируемая функция	    	    
        private double[] _result;//лучшее значение, должно быть установлено для определения измерения аргумента функции	    
        private SuspiciousOptimalPointAndVectorFactory _pointsFactory;//фабрика точек (для разграничения цели поиска: минимум или максимум)

        /// <summary>
        /// Возвращает/устанавливает фабрику точек (для разграничения цели поиска: минимум или максимум)
        /// </summary>
        protected SuspiciousOptimalPointAndVectorFactory PointsFactory
        {
            get
            {
                return _pointsFactory;
            }
            set
            {
                _pointsFactory = value;
            }
        }

        /// <summary>
        /// Возвращает лучшее значение, должно быть установлено для определения измерения аргумента функции
        /// </summary>
        /// <returns></returns>
        protected double[] GetResult()
        {
            return _result;
        }

        /// <summary>
        /// Возвращает/устанавливает оптимизируемую функцию
        /// </summary>
        protected IManyVariableFunction Function
        {
            get
            {
                return _function;
            }
            set
            {
                _function = value;
            }
        }

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="function">Функция, требующая решения</param>
        /// <param name="pointsCreator">Фабрика точек</param>
        /// <param name="initialValue">Начальное значение</param>
        public MultiVariableOptimizer(IManyVariableFunction function, SuspiciousOptimalPointAndVectorFactory pointsCreator, double[] initialValue)
        {
            _function = function;
            _pointsFactory = pointsCreator;
            SetInitialValue(initialValue);
        }

        /// <summary>
        /// Возвращает результат
        /// </summary>
        public virtual double[] Result
        {
            get 
            { 
                return GetResult(); 
            }
        }

        /// <summary>
        /// Устанавливает начальное значение
        /// </summary>
        public void SetInitialValue(double[] newValue)
        {
            _result = newValue;
        }

        /// <summary>
        /// Сортирует точки, наиболее подходящие под оптимальные
        /// </summary>
        /// <param name="bestPoints"></param>
        protected void SortPoints(SuspiciousOptimalVector[] bestPoints)
        {                        
            int bound = bestPoints.Length - 1;            
            while (bound >= 0)
            {
                int m = -1;
                for (int i = 0; i < bound; i++)
                {
                    if (bestPoints[i + 1].BetterThan(bestPoints[i]))
                    {
                        SuspiciousOptimalVector temp = bestPoints[i];
                        bestPoints[i] = bestPoints[i + 1];
                        bestPoints[i + 1] = temp;
                        m = i;
                    }
                }
                bound = m;
            }
        }
    }
}
